package com.bygf.curve.panel;

import com.bygf.curve.Curve;
import com.bygf.curve.Mark;
import com.bygf.curve.WarnLine;
import com.bygf.curve.interfac.MarkChangeListener;
import com.bygf.curve.utils.ChartTransferable;
import com.bygf.curve.utils.Scale;
import com.bygf.curve.utils.Utils;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * 曲线面板，绘制网格线、曲线、标尺、缩放区域，实现拖拽缩放、鼠标悬浮
 *
 * @author sunyupei
 */
public class CurvePanel extends JPanel implements MouseListener, MouseMotionListener, MouseWheelListener {

    ChartPanel chartPanel;
    private CurvePanel instance = this;
    //曲线集合
    private List<Curve> curveList = Collections.synchronizedList(new ArrayList<Curve>());
    //警戒线集合
    private List<WarnLine> warnLineList = new ArrayList<>();
    //是否绘制网格线标识
    private boolean gridVisible = true;
    //网格线颜色
    private Color gridColor = Color.GRAY;
    //网格线画笔样式
    private BasicStroke gridStroke = new BasicStroke(0.5F);
    //背景颜色
    private Color backColor = Color.BLACK;
    //缩放方式
    private int scaleType = Scale.ScaleType_Area;
    //缩放区域
    private Rectangle2D scaleRect = null;
    //缩放区域填充颜色
    private Color scaleRectColor = Color.RED;
    //坐标自适应标识
    private boolean autoAxis = true;
    //辅助操作点
    private Point pressPoint;
    private Point dragPoint;
    private Point dragPointLast;
    private Point clickPoint;
    //标尺1及标尺颜色、画笔样式
    private Mark mark1;
    private Color mark1Color = Color.YELLOW;
    private BasicStroke mark1Stroke = new BasicStroke(1);
    //标尺2及标尺颜色、画笔样式
    private Mark mark2;
    private Color mark2Color = Color.MAGENTA;
    private BasicStroke mark2Stroke = new BasicStroke(1);
    //当前拖拽的标尺
    private Mark selMark;
    //右键菜单资源
    private JPopupMenu rightMenu = new JPopupMenu();
    private JMenu addMarkMenu = new JMenu("增加标尺");
    private JMenu delMarkMenu = new JMenu("删除标尺");
    private JMenu markColorMenu = new JMenu("标尺颜色");
    private JMenuItem addMark1Item = new JMenuItem("标尺1");
    private JMenuItem addMark2Item = new JMenuItem("标尺2");
    private JMenuItem delMark1Item = new JMenuItem("标尺1");
    private JMenuItem delMark2Item = new JMenuItem("标尺2");
    private JMenuItem delMarkAllItem = new JMenuItem("全部");
    private JMenuItem mark1ColorItem = new JMenuItem("标尺1");
    private JMenuItem mark2ColorItem = new JMenuItem("标尺2");
    private JMenuItem copyItem = new JMenuItem("复制");
    private JMenuItem saveImageItem = new JMenuItem("保存");
    private JMenuItem propertyItem = new JMenuItem("属性");
    //鼠标滚轮缩放启用标识
    private boolean mouseWheelZoom = true;
    //菜单中属性是否可以显示
    private boolean propVisible = true;
    // 显示右键菜单
    private boolean showPropMenu = true;

    /**
     * 构造方法
     *
     * @param curvePanel
     */
    public CurvePanel(ChartPanel curvePanel) {
        this.chartPanel = curvePanel;
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        this.addMouseWheelListener(this);
        initRightMenu();
    }

    /**
     * 绘制背景色
     *
     * @param g
     */
    private void drawBackGround(Graphics2D g) {
        g.setColor(backColor);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
    }

    /**
     * 绘制网格线
     *
     * @param g
     */
    private void drawGrid(Graphics2D g) {
        if (!gridVisible) {
            return;
        }
        g.setColor(gridColor);
        g.setStroke(gridStroke);
        Line2D line;
        double mark = this.getWidth() * 1F / chartPanel.getXGridLineCount();
        for (int i = 0; i <= chartPanel.getXGridLineCount(); i++) {
            line = new Line2D.Double(mark * i, 0, mark * i, this.getHeight());
            g.draw(line);
        }
        mark = this.getHeight() * 1F / chartPanel.getYGridLineCount();
        for (int i = 0; i <= chartPanel.getYGridLineCount(); i++) {
            line = new Line2D.Double(0, mark * i, this.getWidth(), mark * i);
            g.draw(line);
        }
    }

    /**
     * 绘制曲线
     *
     * @param g
     */
    private void drawCurve(Graphics2D g) {
        RenderingHints rhBackUp = g.getRenderingHints();
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
        rh.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
        rh.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g.setRenderingHints(rh);
        synchronized (curveList) {
            for (int i = 0; i < curveList.size(); i++) {
                Curve curve = curveList.get(i);
                curve.draw(g, chartPanel);
            }
        }
        g.setRenderingHints(rhBackUp);
    }

    /**
     * 绘制警戒线
     *
     * @param g
     */
    private void drawWarnLine(Graphics2D g) {
        for (int i = 0; i < warnLineList.size(); i++) {
            WarnLine line = warnLineList.get(i);
            line.draw(g, chartPanel);
        }
    }

    /**
     * 绘制图例
     *
     * @param g
     */
    private void drawLegend(Graphics2D g) {
        if (!chartPanel.isLegendVisible()) {
            return;
        }
        float maxNameWidth = 0;
        synchronized (curveList) {
            for (int i = 0; i < curveList.size(); i++) {
                Curve curve = curveList.get(i);
                float nameWidth = Utils.getStringWidth(curve.getName(), null);
                maxNameWidth = maxNameWidth < nameWidth ? nameWidth : maxNameWidth;
            }
        }
        float x = this.getWidth() - maxNameWidth - 20;
        float y = this.getHeight() - curveList.size() * 15;
        g.setFont(new Font("宋体", Font.PLAIN, 12));
        synchronized (curveList) {
            for (int i = 0; i < curveList.size(); i++) {
                Curve curve = curveList.get(i);
                if (!curve.getRender().isCurveVisible()) {
                    continue;
                }
                g.setColor(curve.getRender().getColor());
                g.setStroke(curve.getRender().getStroke());
                Line2D line = new Line2D.Double(x, y - 4, x + 10, y - 4);
                g.draw(line);
                g.drawString(curve.getName(), x + 15, y);
                y += 15;
            }
        }
    }

    /**
     * 绘制标尺
     *
     * @param g
     */
    private void drawMark(Graphics2D g) {
        if (mark1 != null) {
            mark1.draw(g);
        }
        if (mark2 != null) {
            mark2.draw(g);
        }
    }

    /**
     * 绘制缩放矩形框
     *
     * @param g
     */
    private void drawScaleRect(Graphics2D g) {
        g.setColor(scaleRectColor);
        Composite backComposite = g.getComposite();
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3F));
        if (scaleRect != null) {
            g.fill(scaleRect);
        }
        g.setComposite(backComposite);
    }

    /**
     * 双缓冲绘制
     *
     * @param g
     */
    private void doubleBuffer(Graphics2D g) {
        drawBackGround(g);
        drawGrid(g);
        drawCurve(g);
        drawWarnLine(g);
        drawLegend(g);
        drawMark(g);
        drawScaleRect(g);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        BufferedImage bufferedImage = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bufferedImage.createGraphics();
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
        rh.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
        rh.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g2.setRenderingHints(rh);

        doubleBuffer(g2);
        g.drawImage(bufferedImage, 0, 0, null);
    }

    /**
     * 坐标重置
     */
    private void resetAxis() {
        autoAxis = true;
        chartPanel.getXAxis().resetAxis();
        chartPanel.getYAxis().resetAxis();
        chartPanel.getY2Axis().resetAxis();
    }

    /**
     * 缩放，根据拖拽的矩形框调整坐标轴的开始和结束数值
     */
    private void scale() {
        autoAxis = false;
        double xStart = chartPanel.getXAxis().getStartValueNow();
        double xEnd = chartPanel.getXAxis().getEndValueNow();
        double yStart = chartPanel.getYAxis().getStartValueNow();
        double yEnd = chartPanel.getYAxis().getEndValueNow();
        double y2Start = chartPanel.getY2Axis().getStartValueNow();
        double y2End = chartPanel.getY2Axis().getEndValueNow();
        switch (scaleType) {
            case Scale.ScaleType_Horizontal:
                xStart = chartPanel.getXAxis().PixToValue(scaleRect.getMinX());
                xEnd = chartPanel.getXAxis().PixToValue(scaleRect.getMaxX());
                break;
            case Scale.ScaleType_Vertical:
                yStart = chartPanel.getYAxis().PixToValue(scaleRect.getMaxY());
                yEnd = chartPanel.getYAxis().PixToValue(scaleRect.getMinY());
                y2Start = chartPanel.getY2Axis().PixToValue(scaleRect.getMaxY());
                y2End = chartPanel.getY2Axis().PixToValue(scaleRect.getMinY());
                break;
            case Scale.ScaleType_Area:
                xStart = chartPanel.getXAxis().PixToValue(scaleRect.getMinX());
                xEnd = chartPanel.getXAxis().PixToValue(scaleRect.getMaxX());
                yStart = chartPanel.getYAxis().PixToValue(scaleRect.getMaxY());
                yEnd = chartPanel.getYAxis().PixToValue(scaleRect.getMinY());
                y2Start = chartPanel.getY2Axis().PixToValue(scaleRect.getMaxY());
                y2End = chartPanel.getY2Axis().PixToValue(scaleRect.getMinY());
                break;
        }
        if (chartPanel.getXAxis().setValueCheck(xStart, xEnd)) {
            chartPanel.getXAxis().setStartValueNow(xStart);
            chartPanel.getXAxis().setEndValueNow(xEnd);
        }
        if (chartPanel.getYAxis().setValueCheck(yStart, yEnd)) {
            chartPanel.getYAxis().setStartValueNow(yStart);
            chartPanel.getYAxis().setEndValueNow(yEnd);
        }
        if (chartPanel.getY2Axis().setValueCheck(y2Start, y2End)) {
            chartPanel.getY2Axis().setStartValueNow(y2Start);
            chartPanel.getY2Axis().setEndValueNow(y2End);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        clickPoint = e.getPoint();
        if (e.getButton() == MouseEvent.BUTTON3) {
            addMark1Item.setEnabled(mark1 == null);
            delMark1Item.setEnabled(mark1 != null);
            addMark2Item.setEnabled(mark2 == null);
            delMark2Item.setEnabled(mark2 != null);
            delMarkAllItem.setEnabled(mark1 != null || mark2 != null);
            mark1ColorItem.setEnabled(mark1 != null);
            mark2ColorItem.setEnabled(mark2 != null);
            if (showPropMenu) {
                rightMenu.show(this, e.getX(), e.getY());
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        pressPoint = e.getPoint();
        if (mark1 != null && mark1.isOnMark(e.getPoint())) {
            selMark = mark1;
        } else if (mark2 != null && mark2.isOnMark(e.getPoint())) {
            selMark = mark2;
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (scaleRect != null) {
            if (scaleRect.getWidth() < 0 || scaleRect.getHeight() < 0) {
                resetAxis();
            } else {
                scale();
            }
        }
        selMark = null;
        scaleRect = null;
        pressPoint = null;
        dragPoint = null;
        this.repaint();
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        dragPoint = e.getPoint();
        if (dragPointLast == null) {
            dragPointLast = e.getPoint();
        }
        if (pressPoint == null) {
            pressPoint = e.getPoint();
        }
        if (selMark != null) {
            double xValue = chartPanel.getXAxis().PixToValue(e.getPoint().x);
            double yValue = chartPanel.getYAxis().PixToValue(e.getPoint().y);
            selMark.setxValue(xValue);
            selMark.setyValue(yValue);
            if (chartPanel.getMarkListener() != null) {
                if (selMark.equals(mark1)) {
                    chartPanel.getMarkListener().mark1Change(MarkChangeListener.State_Move);
                } else {
                    chartPanel.getMarkListener().mark2Change(MarkChangeListener.State_Move);
                }
            }
        } else {
            switch (scaleType) {
                case Scale.ScaleType_Horizontal:
                    scaleRect = new Rectangle2D.Double(pressPoint.getX(), 0, dragPoint.getX() - pressPoint.getX(), this.getHeight());
                    break;
                case Scale.ScaleType_Vertical:
                    scaleRect = new Rectangle2D.Double(0, pressPoint.getY(), this.getWidth(), dragPoint.getY() - pressPoint.getY());
                    break;
                case Scale.ScaleType_Area:
                    scaleRect = new Rectangle2D.Double(pressPoint.getX(), pressPoint.getY(), dragPoint.getX() - pressPoint.getX(), dragPoint.getY() - pressPoint.getY());
                    break;
            }
        }
        this.repaint();
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        if (mark1 != null && mark1.isOnMark(e.getPoint())) {
            setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
        } else if (mark2 != null && mark2.isOnMark(e.getPoint())) {
            setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
        } else {
            setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
        String toolTip = null;
        synchronized (curveList) {
            for (int i = 0; i < curveList.size(); i++) {
                Curve curve = curveList.get(i);
                toolTip = curve.getToolTip(e.getPoint());
                if (toolTip != null) {
                    break;
                }
            }
        }
        setToolTipText(toolTip);
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        if (!mouseWheelZoom) {
            return;
        }
        if (e == null) {
            return;
        }
        autoAxis = false;
        if (e.isControlDown()) {
            //鼠标位置的Y值相对于曲线面板高度的比例
            double scale = e.getY() * 1F / this.getHeight();
            //缩放步长值
            double cha = (chartPanel.getYAxis().getEndValueNow() - chartPanel.getYAxis().getStartValueNow()) / (chartPanel.getYGridLineCount() + 1);
            //根据缩放步长及相对比例更新Y轴开始和结束位置数值
            double yStart = chartPanel.getYAxis().getStartValueNow() + cha * (1 - scale) * e.getWheelRotation();
            double yEnd = chartPanel.getYAxis().getEndValueNow() - cha * scale * e.getWheelRotation();
            if (chartPanel.getYAxis().setValueCheck(yStart, yEnd)) {
                chartPanel.getYAxis().setStartValueNow(yStart);
                chartPanel.getYAxis().setEndValueNow(yEnd);
            }
            double cha2 = (chartPanel.getY2Axis().getEndValueNow() - chartPanel.getY2Axis().getStartValueNow()) / (chartPanel.getYGridLineCount() + 1);
            double y2Start = chartPanel.getY2Axis().getStartValueNow() + cha2 * (1 - scale) * e.getWheelRotation();
            double y2End = chartPanel.getY2Axis().getEndValueNow() - cha2 * scale * e.getWheelRotation();
            if (chartPanel.getY2Axis().setValueCheck(y2Start, y2End)) {
                chartPanel.getY2Axis().setStartValueNow(y2Start);
                chartPanel.getY2Axis().setEndValueNow(y2End);
            }
        } else {
            //鼠标位置的X值相对于曲线面板宽度的比例
            double scale = e.getX() * 1F / this.getWidth();
            //缩放步长值
            double cha = (chartPanel.getXAxis().getEndValueNow() - chartPanel.getXAxis().getStartValueNow()) / (chartPanel.getXGridLineCount() + 1);
            //根据缩放步长及相对比例更新X轴开始和结束位置数值
            double xStart = chartPanel.getXAxis().getStartValueNow() + cha * scale * e.getWheelRotation();
            double xEnd = chartPanel.getXAxis().getEndValueNow() - cha * (1 - scale) * e.getWheelRotation();
            if (chartPanel.getXAxis().setValueCheck(xStart, xEnd)) {
                chartPanel.getXAxis().setStartValueNow(xStart);
                chartPanel.getXAxis().setEndValueNow(xEnd);
            }
        }
        this.repaint();
    }

    /**
     * @return the gridColor
     */
    public Color getGridColor() {
        return gridColor;
    }

    /**
     * @param gridColor the gridColor to set
     */
    public void setGridColor(Color gridColor) {
        this.gridColor = gridColor;
    }

    /**
     * @return the gridStroke
     */
    public BasicStroke getGridStroke() {
        return gridStroke;
    }

    /**
     * @param gridStroke the gridStroke to set
     */
    public void setGridStroke(BasicStroke gridStroke) {
        this.gridStroke = gridStroke;
    }

    /**
     * @return the backColor
     */
    public Color getBackColor() {
        return backColor;
    }

    /**
     * @param backColor the backColor to set
     */
    public void setBackColor(Color backColor) {
        this.backColor = backColor;
    }

    /**
     * @return the scaleType
     */
    public int getScaleType() {
        return scaleType;
    }

    /**
     * @param scaleType the scaleType to set
     */
    public void setScaleType(int scaleType) {
        if (scaleType != Scale.ScaleType_Area && scaleType != Scale.ScaleType_Horizontal
                && scaleType != Scale.ScaleType_Vertical && scaleType != Scale.ScaleType_None) {
            throw new IllegalArgumentException("缩放类型应该为0或1或2或3");
        } else {
            this.scaleType = scaleType;
        }
    }

    /**
     * @return the scaleRectColor
     */
    public Color getScaleRectColor() {
        return scaleRectColor;
    }

    /**
     * @param scaleRectColor the scaleRectColor to set
     */
    public void setScaleRectColor(Color scaleRectColor) {
        this.scaleRectColor = scaleRectColor;
    }

    /**
     * @return the mark1
     */
    public Mark getMark1() {
        return mark1;
    }

    /**
     * @param mark1 the mark1 to set
     */
    public void setMark1(Mark mark1) {
        this.mark1 = mark1;
    }

    /**
     * @return the mark1Color
     */
    public Color getMark1Color() {
        return mark1Color;
    }

    /**
     * @param mark1Color the mark1Color to set
     */
    public void setMark1Color(Color mark1Color) {
        this.mark1Color = mark1Color;
        if (mark1 != null) {
            mark1.setColor(mark1Color);
        }
    }

    /**
     * @return the mark2
     */
    public Mark getMark2() {
        return mark2;
    }

    /**
     * @param mark2 the mark2 to set
     */
    public void setMark2(Mark mark2) {
        this.mark2 = mark2;
    }

    /**
     * @return the mark2Color
     */
    public Color getMark2Color() {
        return mark2Color;
    }

    /**
     * @param mark2Color the mark2Color to set
     */
    public void setMark2Color(Color mark2Color) {
        this.mark2Color = mark2Color;
        if (mark2 != null) {
            mark2.setColor(mark2Color);
        }
    }

    /**
     * @return the mark1Stroke
     */
    public BasicStroke getMark1Stroke() {
        return mark1Stroke;
    }

    /**
     * @param mark1Stroke the mark1Stroke to set
     */
    public void setMark1Stroke(BasicStroke mark1Stroke) {
        this.mark1Stroke = mark1Stroke;
        if (mark1 != null) {
            mark1.setStroke(mark1Stroke);
        }
    }

    /**
     * @return the mark2Stroke
     */
    public BasicStroke getMark2Stroke() {
        return mark2Stroke;
    }

    /**
     * @param mark2Stroke the mark2Stroke to set
     */
    public void setMark2Stroke(BasicStroke mark2Stroke) {
        this.mark2Stroke = mark2Stroke;
        if (mark2 != null) {
            mark2.setStroke(mark2Stroke);
        }
    }

    /**
     * @return the curveCollection
     */
    public List<Curve> getCurveList() {
        return curveList;
    }

    /**
     * @param curveList the curveCollection to set
     */
    public void setCurveList(List<Curve> curveList) {
        this.curveList = curveList;
    }

    /**
     * @return the warnLineList
     */
    public List<WarnLine> getWarnLineList() {
        return warnLineList;
    }

    /**
     * @param warnLineList the warnLineList to set
     */
    public void setWarnLineList(List<WarnLine> warnLineList) {
        this.warnLineList = warnLineList;
    }

    /**
     * 将当前曲线界面复制到剪切板
     */
    private void copy() {
        BufferedImage bufferedImage = Utils.printScreen(chartPanel);
        Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        systemClipboard.setContents(new ChartTransferable(bufferedImage), null);
    }

    /**
     * 保存图片
     */
    private void saveImage() {
        BufferedImage bufferedImage = Utils.printScreen(chartPanel);
        byte[] imageByte = Utils.Image2Byte(bufferedImage);
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("保存图片");
        fileChooser.removeChoosableFileFilter(fileChooser.getAcceptAllFileFilter());//移除所有文件选择
        fileChooser.setFileFilter(new FileNameExtensionFilter("图片文件", "jpg"));
        if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
            String imageName = Utils.saveFile(imageByte, fileChooser.getSelectedFile().getPath() + ".jpg");
            if (imageName == null) {
                Utils.ShowInformation(this, "保存失败！");
            } else {
                Utils.ShowInformation(this, "保存成功，文件路径：" + imageName);
            }
        }
    }

    /**
     * 获取曲线截图
     *
     * @return
     */
    public BufferedImage printScreen() {
        return Utils.printScreen(chartPanel);
    }

    /**
     * @return the bMouseWheelZoom
     */
    public boolean isMouseWheelZoom() {
        return mouseWheelZoom;
    }

    /**
     * @param MouseWheelZoom the bMouseWheelZoom to set
     */
    public void setMouseWheelZoom(boolean MouseWheelZoom) {
        this.mouseWheelZoom = MouseWheelZoom;
    }

    /**
     * @return the gridVisible
     */
    public boolean isGridVisible() {
        return gridVisible;
    }

    /**
     * @param gridVisible the gridVisible to set
     */
    public void setGridVisible(boolean gridVisible) {
        this.gridVisible = gridVisible;
    }

    /**
     * @return the autoAxis
     */
    public boolean isAutoAxis() {
        return autoAxis;
    }

    /**
     * @param autoAxis the autoAxis to set
     */
    public void setAutoAxis(boolean autoAxis) {
        this.autoAxis = autoAxis;
    }

    /**
     * 初始化右键菜单
     */
    private void initRightMenu() {
        addMark1Item.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                double xValue = chartPanel.getXAxis().PixToValue(clickPoint.x);
                double yValue = chartPanel.getYAxis().PixToValue(clickPoint.y);
                double y2Value = chartPanel.getY2Axis().PixToValue(clickPoint.y);
                setMark1(new Mark(xValue, yValue, y2Value, chartPanel));
                getMark1().setColor(getMark1Color());
                instance.repaint();
                if (chartPanel.getMarkListener() != null) {
                    chartPanel.getMarkListener().mark1Change(MarkChangeListener.State_Add);
                }
            }
        });
        addMark2Item.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                double xValue = chartPanel.getXAxis().PixToValue(clickPoint.x);
                double yValue = chartPanel.getYAxis().PixToValue(clickPoint.y);
                double y2Value = chartPanel.getY2Axis().PixToValue(clickPoint.y);
                setMark2(new Mark(xValue, yValue, y2Value, chartPanel));
                getMark2().setColor(getMark2Color());
                instance.repaint();
                if (chartPanel.getMarkListener() != null) {
                    chartPanel.getMarkListener().mark2Change(MarkChangeListener.State_Add);
                }
            }
        });
        addMarkMenu.add(addMark1Item);
        addMarkMenu.add(addMark2Item);
        delMark1Item.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setMark1(null);
                instance.repaint();
                if (chartPanel.getMarkListener() != null) {
                    chartPanel.getMarkListener().mark1Change(MarkChangeListener.State_Del);
                }
            }
        });
        delMark2Item.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setMark2(null);
                instance.repaint();
                if (chartPanel.getMarkListener() != null) {
                    chartPanel.getMarkListener().mark2Change(MarkChangeListener.State_Del);
                }
            }
        });
        delMarkAllItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setMark1(null);
                setMark2(null);
                instance.repaint();
                if (chartPanel.getMarkListener() != null) {
                    chartPanel.getMarkListener().mark1Change(MarkChangeListener.State_Del);
                }
                if (chartPanel.getMarkListener() != null) {
                    chartPanel.getMarkListener().mark2Change(MarkChangeListener.State_Del);
                }
            }
        });
        delMarkMenu.add(delMark1Item);
        delMarkMenu.add(delMark2Item);
        delMarkMenu.add(delMarkAllItem);
        mark1ColorItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Color c = JColorChooser.showDialog(instance, "颜色选择", mark1Color);
                if (c != null) {
                    mark1Color = c;
                    mark1.setColor(c);
                    instance.repaint();
                }
            }
        });
        mark2ColorItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Color c = JColorChooser.showDialog(instance, "颜色选择", mark2Color);
                if (c != null) {
                    mark2Color = c;
                    mark2.setColor(c);
                    instance.repaint();
                }
            }
        });
        markColorMenu.add(mark1ColorItem);
        markColorMenu.add(mark2ColorItem);
        copyItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                copy();
            }
        });
        saveImageItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                saveImage();
            }
        });
        propertyItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                PropertyDialog dialog = PropertyDialog.getInstance(chartPanel);
                dialog.setpropVisible(propVisible);
                Utils.CenterDialog(dialog);
            }
        });
        rightMenu.add(addMarkMenu);
        rightMenu.add(delMarkMenu);
        rightMenu.add(markColorMenu);
        rightMenu.add(copyItem);
        rightMenu.add(saveImageItem);
        rightMenu.add(propertyItem);
    }

    /**
     * @param propVisible the propVisible to set
     */
    public void setPropVisible(boolean propVisible) {
        this.propVisible = propVisible;
    }

    /**
     * @return the showPropMenu
     */
    public boolean getShowPropMenu() {
        return showPropMenu;
    }

    /**
     * @param showPropMenu the showPropMenu to set
     */
    public void setShowPropMenu(boolean showPropMenu) {
        this.showPropMenu = showPropMenu;
    }
}
